package com.paishen.libamap.poisearch;

import android.Manifest;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentActivity;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.maps2d.AMap;
import com.amap.api.maps2d.CameraUpdateFactory;
import com.amap.api.maps2d.SupportMapFragment;
import com.amap.api.maps2d.model.LatLng;
import com.amap.api.maps2d.overlay.PoiOverlay;
import com.amap.api.services.core.AMapException;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.core.PoiItem;
import com.amap.api.services.core.SuggestionCity;
import com.amap.api.services.help.Inputtips;
import com.amap.api.services.help.Tip;
import com.amap.api.services.poisearch.PoiResult;
import com.amap.api.services.poisearch.PoiSearch;
import com.paishen.libamap.R;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;


public class PoiKeywordSearchActivity extends FragmentActivity {
    public static final String EXTRA_TYPE_SEARCH = "extra_type_search";
    public static final String EXTRA_POI = "extra_poi";
    public static final String EXTRA_LAT = "extra_lat";
    public static final String EXTRA_LNG = "extra_lng";

    private String typeSearch;
    private static final int CODE_FOR_LOCATION_PERMISSION = 21;

    private AMap aMap;

    private AMapLocationClient locationClient = null;
    private AMapLocationClientOption locationOption = null;
    private PoiSearch.Query query;// Poi查询条件类
    private PoiSearch poiSearch;// POI搜索
    private PoiResult poiResult; // poi返回的结果
    private String selectedKey;

    private ProgressDialog dlgLocLoading;
    private AlertDialog dlgLocRetry;
    private AMapLocation aMapLocation;

    private EditText edSearch;
    private ListView listResult, listKey;

    private List<Tip> tipList;
    private List<PoiItem> poiItems;

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == CODE_FOR_LOCATION_PERMISSION) {
            if (permissions[0].equals(Manifest.permission.ACCESS_FINE_LOCATION)
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                if (!dlgLocLoading.isShowing()) dlgLocLoading.show();
                // 启动定位
                locationClient.startLocation();
            } else {
                if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
                    AlertDialog dialog = new AlertDialog.Builder(this)
                            .setMessage(R.string.request_permission_location)
                            .setPositiveButton(R.string.go_1, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    Uri packageURI = Uri.parse("package:" + getPackageName());
                                    Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageURI);
                                    startActivity(intent);
                                    dialog.dismiss();
                                }
                            })
                            .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    dialog.dismiss();
                                    finish();
                                }
                            }).create();
                    dialog.show();
                    return;
                }
            }
        }
    }

    private void showLocRetryDialog() {

        // 检测是否包含定位权限
        int r1 = checkOp(0); // AppOpsManager.OP_COARSE_LOCATION
        int r2 = checkOp(1); // AppOpsManager.OP_FINE_LOCATION
        final boolean isNoPermission = r1 != 0 || r2 != 0;

        int message = isNoPermission ? R.string.location_retry_permission : R.string.location_retry_net;

        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle(R.string.location_fail).setMessage(message).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dlgLocRetry.dismiss();
                finish();
            }
        });
        builder.setPositiveButton(R.string.confirm, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dlgLocRetry.dismiss();
                if (isNoPermission) {
                    Uri packageURI = Uri.parse("package:" + getPackageName());
                    Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageURI);
                    startActivity(intent);
                } else {
                    if (!dlgLocLoading.isShowing()) dlgLocLoading.show();
                    // 启动定位
                    locationClient.startLocation();
                }
            }
        });

        dlgLocRetry = builder.setCancelable(false).create();

        if (dlgLocLoading != null) dlgLocLoading.dismiss();
        if (!dlgLocRetry.isShowing()) dlgLocRetry.show();
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {


        typeSearch = getString(R.string.location_default_search);
        getWindow().setBackgroundDrawableResource(android.R.color.transparent);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            // 透明状态栏
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_poi_keyword_search);

        setStatusBarDarkMode(true, PoiKeywordSearchActivity.this);

        findViewById(R.id.lay_title).setPadding(0, (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT ? Util.getStatusBarHeight(this) : 0), 0, 0);

        findViewById(R.id.img_back).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
        edSearch = (EditText) findViewById(R.id.ed_search);


        edSearch.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
            }

            @Override
            public void afterTextChanged(Editable s) {
                String newText = s.toString().trim();

                if (TextUtils.equals(selectedKey, newText)) {
                    selectedKey = "";
                    return;
                }
                Inputtips inputTips = new Inputtips(PoiKeywordSearchActivity.this,
                        new Inputtips.InputtipsListener() {
                            @Override
                            public void onGetInputtips(List<Tip> tipList, int rCode) {
                                if (rCode == 0) {// 正确返回
                                    PoiKeywordSearchActivity.this.tipList = tipList;
                                    adapterKey.notifyDataSetChanged();
                                    listKey.setVisibility(View.VISIBLE);
                                }
                            }
                        });
                try {
                    if (aMapLocation != null) {
                        String city = aMapLocation.getCity();
                        if (!TextUtils.isEmpty(city)) {
                            inputTips.requestInputtips(newText, city);// 第一个参数表示提示关键字，第二个参数默认代表全国，也可以为城市区号
                        }
                    }
                } catch (AMapException e) {
                    e.printStackTrace();
                }
            }
        });

        String defaultKey = getIntent().getStringExtra(EXTRA_TYPE_SEARCH);
        if (!TextUtils.isEmpty(defaultKey)) {
            edSearch.setText(defaultKey);
        }

        listResult = (ListView) findViewById(R.id.list_result);
        listResult.setAdapter(adapterResult);
        listResult.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Intent intent = getIntent();
                PoiItem pi = poiItems.get(position);
                intent.putExtra(EXTRA_POI, pi.getTitle() + " " + pi.getSnippet());
                intent.putExtra(EXTRA_LAT, pi.getLatLonPoint().getLatitude());
                intent.putExtra(EXTRA_LNG, pi.getLatLonPoint().getLongitude());
                setResult(RESULT_OK, intent);
                finish();
            }
        });
        listKey = (ListView) findViewById(R.id.list_key);
        listKey.setAdapter(adapterKey);
        listKey.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                hideSoftInputFromWindowAlways(PoiKeywordSearchActivity.this);
                listKey.setVisibility(View.GONE);
                Tip tip = tipList.get(position);
                if (tip != null) {
                    edSearch.setText(selectedKey = tip.getName());
                    AMapLocation lkey = new AMapLocation("");
                    LatLonPoint point = tip.getPoint();
                    if (point != null) {
                        lkey.setLatitude(point.getLatitude());
                        lkey.setLongitude(point.getLongitude());
                        doSearchQuery(lkey, 0);
                    } else {

                        Toast.makeText(getApplicationContext(), "位置获取失败", Toast.LENGTH_SHORT).show();
                    }
                }
            }
        });

        aMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();


        double defaultLat = getIntent().getDoubleExtra(EXTRA_LAT, 0);
        double defaultLng = getIntent().getDoubleExtra(EXTRA_LNG, 0);
        if (defaultLat * defaultLng > 0) {
            aMap.moveCamera(CameraUpdateFactory.changeLatLng(new LatLng(defaultLat, defaultLng)));
        }

        locationClient = new AMapLocationClient(getApplicationContext());
        locationOption = new AMapLocationClientOption();
        // 设置定位模式为高精度模式
        locationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
        // 设置是否需要显示地址信息
        locationOption.setNeedAddress(true);
        /**
         * 设置是否优先返回GPS定位结果，如果30秒内GPS没有返回定位结果则进行网络定位
         * 注意：只有在高精度模式下的单次定位有效，其他方式无效
         */
        locationOption.setGpsFirst(false);
        locationOption.setOnceLocation(true);
        // 设置定位监听
        locationClient.setLocationListener(new AMapLocationListener() {
            @Override
            public void onLocationChanged(AMapLocation aMapLocation) {
                // 停止定位
                locationClient.stopLocation();

                if (aMapLocation != null && aMapLocation.getErrorCode() == 0) {
                    PoiKeywordSearchActivity.this.aMapLocation = aMapLocation;

                    selectedKey = aMapLocation.getAddress();
                    doSearchQuery(aMapLocation, 0);
                } else {
                    showLocRetryDialog();
                }
            }
        });


        // 设置定位参数
        locationClient.setLocationOption(locationOption);
        dlgLocLoading = ProgressDialog.show(this, getString(R.string.location_search), getString(R.string.location_loading), true, false);

        int hasLocationPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
        if (hasLocationPermission != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                    CODE_FOR_LOCATION_PERMISSION);
            return;
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        int hasLocationPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
        if (hasLocationPermission == PackageManager.PERMISSION_GRANTED) {

            if (!dlgLocLoading.isShowing()) dlgLocLoading.show();
            // 启动定位
            locationClient.startLocation();
        }

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (null != locationClient) {
            /**
             * 如果AMapLocationClient是在当前Activity实例化的，
             * 在Activity的onDestroy中一定要执行AMapLocationClient的onDestroy
             */
            locationClient.onDestroy();
            locationClient = null;
            locationOption = null;
        }
    }


    /**
     * 开始进行poi搜索
     */
    protected void doSearchQuery(AMapLocation aMapLocation, int pageNum) {
        query = new PoiSearch.Query(edSearch.getText().toString(), typeSearch, aMapLocation.getCity());// 第一个参数表示搜索字符串，第二个参数表示poi搜索类型，第三个参数表示poi搜索区域（空字符串代表全国）
        query.setPageSize(15);// 设置每页最多返回多少条poiitem
        query.setPageNum(pageNum);// 设置查第一页

        poiSearch = new PoiSearch(this, query);
        poiSearch.setBound(new PoiSearch.SearchBound(new LatLonPoint(aMapLocation.getLatitude(),
                aMapLocation.getLongitude()), 3000));//设置周边搜索的中心点以及区域
        poiSearch.setOnPoiSearchListener(onPoiSearchListener);
        poiSearch.searchPOIAsyn();
    }

    private PoiSearch.OnPoiSearchListener onPoiSearchListener = new PoiSearch.OnPoiSearchListener() {
        @Override
        public void onPoiSearched(PoiResult result, int rCode) {
            if (dlgLocLoading.isShowing()) dlgLocLoading.dismiss();
            if (rCode == 0) {
                if (result != null && result.getQuery() != null) {// 搜索poi的结果
                    if (result.getQuery().equals(query)) {// 是否是同一条
                        poiResult = result;
                        // 取得搜索到的poiitems有多少页
                        List<PoiItem> poiItems = poiResult.getPois();// 取得第一页的poiitem数据，页数从数字0开始

                        List<SuggestionCity> suggestionCities = poiResult
                                .getSearchSuggestionCitys();// 当搜索不到poiitem数据时，会返回含有搜索关键字的城市信息

                        if (poiItems != null && poiItems.size() > 0) {
                            aMap.clear();// 清理之前的图标
                            PoiOverlay poiOverlay = new PoiOverlay(aMap, poiItems);
                            poiOverlay.removeFromMap();
                            poiOverlay.addToMap();
                            poiOverlay.zoomToSpan();

                            PoiKeywordSearchActivity.this.poiItems = poiItems;
                            adapterResult.notifyDataSetChanged();
                        } else if (suggestionCities != null
                                && suggestionCities.size() > 0) {
                            String infomation = "推荐城市\n";
                            for (int i = 0; i < suggestionCities.size(); i++) {
                                infomation += "城市名称:" + suggestionCities.get(i).getCityName() + "城市区号:"
                                        + suggestionCities.get(i).getCityCode() + "城市编码:"
                                        + suggestionCities.get(i).getAdCode() + "\n";
                            }
                            showToast(infomation);
                        } else {
                            showToast(R.string.no_result);
                        }
                    }
                } else {
                    showToast(R.string.no_result);
                }
            } else if (rCode == 27) {
                showToast(R.string.error_network);
            } else if (rCode == 32) {
                showToast(R.string.error_key);
            } else {
                showToast(getString(R.string.error_other) + rCode);
            }
        }
    };

    private void showToast(int textId) {
        showToast(getString(textId));
    }

    private void showToast(String text) {
        Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
    }

    /**
     * 隐藏输入法
     *
     * @param context Activity
     */
    private void hideSoftInputFromWindowAlways(Activity context) {
        if (context.getCurrentFocus() != null) {
            ((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(context.getCurrentFocus()
                    .getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
        }
    }

    private BaseAdapter adapterResult = new BaseAdapter() {
        @Override
        public int getCount() {
            return poiItems != null ? poiItems.size() : 0;
        }

        @Override
        public Object getItem(int position) {
            return poiItems != null ? poiItems.get(position) : 0;
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        class ViewHolder {
            TextView txName, txAddress;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null) {
                convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_poi_result, null);
            }
            ViewHolder viewHolder = (ViewHolder) convertView.getTag();
            if (viewHolder == null) {
                viewHolder = new ViewHolder();
                viewHolder.txName = (TextView) convertView.findViewById(R.id.tx_name);
                viewHolder.txAddress = (TextView) convertView.findViewById(R.id.tx_address);
                convertView.setTag(viewHolder);
            }
            PoiItem pi = poiItems.get(position);
            viewHolder.txName.setText(pi.getTitle());
            viewHolder.txAddress.setText(pi.getSnippet());
            return convertView;
        }
    };

    private BaseAdapter adapterKey = new BaseAdapter() {
        @Override
        public int getCount() {
            return tipList != null ? tipList.size() : 0;
        }

        @Override
        public Object getItem(int position) {
            return tipList != null ? tipList.get(position) : 0;
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null) {
                convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_poi_key, null);
            }
            ((TextView) convertView).setText(tipList.get(position).getName());
            return convertView;
        }
    };

    private int checkOp(int op) {

        final int version = Build.VERSION.SDK_INT;
        if (version >= Build.VERSION_CODES.KITKAT) {
            Object object = getSystemService("appops");
            Class c = object.getClass();
            try {
                Class[] cArg = new Class[3];
                cArg[0] = int.class;
                cArg[1] = int.class;
                cArg[2] = String.class;
                Method lMethod = c.getDeclaredMethod("checkOp", cArg);
                return (Integer) lMethod.invoke(object, op, Binder.getCallingUid(), getPackageName());
            } catch (Exception e) {
                e.printStackTrace();
                return -1;
            }
        } else {
            return -2;
        }
    }

    private void setStatusBarDarkMode(boolean darkmode, Activity activity) {
        if ("Xiaomi".equalsIgnoreCase(Build.BRAND)) {
            Class<? extends Window> clazz = activity.getWindow().getClass();
            try {
                int darkModeFlag;
                Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
                Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
                darkModeFlag = field.getInt(layoutParams);
                Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
                extraFlagField.invoke(activity.getWindow(), darkmode ? darkModeFlag : 0, darkModeFlag);
            } catch (Exception e) {
                Log.e("PoiKeywordSearchActivity", "Xiaomi setStatusBarDarkIcon: failed");
            }
        } else if ("MeiZu".equalsIgnoreCase(Build.BRAND)) {
            Window window = activity.getWindow();
            if (window != null) {
                try {
                    WindowManager.LayoutParams lp = window.getAttributes();
                    Field darkFlag = WindowManager.LayoutParams.class.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
                    Field meizuFlags = WindowManager.LayoutParams.class.getDeclaredField("meizuFlags");
                    darkFlag.setAccessible(true);
                    meizuFlags.setAccessible(true);
                    int bit = darkFlag.getInt(null);
                    int value = meizuFlags.getInt(lp);
                    if (darkmode) {
                        value |= bit;
                    } else {
                        value &= ~bit;
                    }
                    meizuFlags.setInt(lp, value);
                    window.setAttributes(lp);
                } catch (Exception e) {
                    Log.e("PoiKeywordSearchActivity", "MeiZu setStatusBarDarkIcon: failed");
                }
            }
        }
    }
}
